﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;
using SchoolManagerMVC.Web.Areas.Departments.Controllers;
using System.Web.Mvc;
using SchoolManagerMVC.Web.Models;
using Moq;
using SchoolManagerMVC.BusinessAbstract.Interfaces;
using SchoolManagerMVC.Repository.EntityFramework;
using SchoolManagerMVC.Web.ViewModel;
using SchoolManagerMVC.BusinessConcrete.Reporting;

namespace SchoolManagerMVC.Tests.Controllers.DepartmentArea
{
    [TestClass]
    public class HomeControllerTest
    {
        Mock<IRepository> _repoMock;
        HomeController controller;

        Department department;
        Messages goodMessage,badMessage;

        [TestInitialize]
        public void setup()
        {
            goodMessage = new Messages()
            {
                Message="",
                result = true
            };

            badMessage = new Messages()
            {
                Message = "",
                result = false
            };

            department = new Department()
            {
                DepartmentHead = Guid.NewGuid(),
                DepartmentID = 1
            };

            _repoMock = new Mock<IRepository>();
            controller = new HomeController(_repoMock.Object);

            _repoMock.Setup(x => x.GetAll<Department>()).Returns(new List<Department>());
            _repoMock.Setup(x => x.Add<Department>(It.IsAny<Department>())).Returns(goodMessage);
            _repoMock.Setup(x => x.Remove<Department>(It.IsAny<Department>())).Returns(goodMessage);
            _repoMock.Setup(x => x.GetSingle<Department>(It.IsAny<Func<Department, bool>>())).Returns(department);
        }

        [TestMethod]
        public void Authorization_Attributes_Have_Been_Applied()
        {
            var attributes = typeof(HomeController).GetCustomAttributes(typeof(AuthorizeAttribute), true);
            
            Assert.IsNotNull(attributes);
            Assert.AreEqual(1, attributes.Length);
            var authAttribute = (AuthorizeAttribute)attributes[0];
            string[] roles = authAttribute.Roles.Split(new char[] { ',' });
            Assert.IsTrue(roles.Contains(Constants.Admin));
            Assert.IsTrue(roles.Contains(Constants.OfficeAdmin));
            Assert.IsTrue(roles.Count()== 2);
        }

        [TestMethod]
        public void Index_GoesTo_Index_View()
        {
            ViewResult result = controller.Index() as ViewResult;
            Assert.AreEqual("Index", result.ViewName);
            Assert.IsNotNull(result.Model);

            var model = result.Model;
        }

        [TestMethod]
        public void Create_Get_GoesTo_Create_View()
        {
            var result = controller.Create() as ViewResult;
            Assert.AreEqual("Create", result.ViewName);
        }

        [TestMethod]
        public void Create_Post_BadModel_GoesTo_Create()
        {
            controller.ModelState.AddModelError("", "Error");
            var result = controller.Create(department) as ViewResult;

            Assert.AreEqual("Create", result.ViewName);
            Assert.IsNotNull(result.Model);
        }

        [TestMethod]
        public void Good_Model_GoesTo_Default()
        {
            var result = controller.Create(department) as RedirectToRouteResult;            
            Assert.AreEqual("Departments", result.RouteName);
        }

        [TestMethod]
        public void Null_ID_Details_GoesTo_Default()
        {
            var result = controller.Details(null) as RedirectToRouteResult;
            Assert.AreEqual("Departments", result.RouteName);
        }

        [TestMethod]
        public void Null_ID_DeleteGet_GoesTo_Default()
        {
            int? id = null;
            var result = controller.Delete(id) as RedirectToRouteResult;
            Assert.AreEqual("Departments", result.RouteName);
        }

        [TestMethod]
        public void Bad_Post_GoesTo_Default()
        {

            var result = controller.Delete(new DepartmentViewModel() { department = new Department() { DepartmentID = 0 } }) as RedirectToRouteResult;
            Assert.AreEqual("Departments", result.RouteName);
        }

        [TestMethod]
        public void Bad_Delete_GoesTo_DeleteView()
        {
            _repoMock.Setup(x => x.Remove<Department>(It.IsAny<Department>())).Returns(badMessage);
            var result = controller.Delete(new DepartmentViewModel(){department = department}) as ViewResult;
            Assert.AreEqual("Delete", result.ViewName);
            Assert.IsNotNull(result.Model);
        }

        [TestMethod]
        public void Good_Delete_GoesTo_Default()
        {
            var result = controller.Delete(new DepartmentViewModel() { department = department }) as RedirectToRouteResult;
            Assert.AreEqual("Departments", result.RouteName);
        }

        [TestMethod]
        public void Null_Edit_GoesTo_Default()
        {
            int? id = null;
            var result = controller.Delete(id) as RedirectToRouteResult;
            Assert.AreEqual("Departments", result.RouteName);
        }

        [TestMethod]
        public void Null_Result_EditGet_RedirectsTo_Default()
        {
            _repoMock.Setup(x => x.GetSingle<Department>(It.IsAny<Func<Department, bool>>())).Returns(null);
            var result = controller.Edit(1) as RedirectToRouteResult;
            Assert.AreEqual("Departments", result.RouteName);
        }

        [TestMethod]
        public void Good_EditGet_Returns_Edit_View()
        {
            var result = controller.Edit(1) as ViewResult;
            Assert.AreEqual("Edit", result.ViewName);
            Assert.IsNotNull(result.Model);
        }

        [TestMethod]
        public void Bad_Model_DetailsPost_GoesTo_Edit()
        {
            controller.ModelState.AddModelError("", "Error");
            var result = controller.Edit(department) as ViewResult;
            Assert.AreEqual("Edit", result.ViewName);
            Assert.IsNotNull(result.Model);
        }

        [TestMethod]
        public void Good_EditPost_Returns_Details_View()
        {
            var result = controller.Edit(department) as RedirectToRouteResult;
            Assert.AreEqual("Details", result.RouteValues["action"]);
        }
    }
}
